#include <conio.h>
#include <stdio.h>
#include <alloc.h>
#include <string.h>
#include <math.h>

#define Null 0;
void  LoadAuthorRecord();
void  LoadPubRecord();
void  LoadToBookRefer(struct myRefer **q);

void AssignAuthorRefer(int index);
void AssignPubRefer(int index);
void AssignBookRefer(struct myRefer **p);

void  SearchByISBN();
void  SearchByTitle();

void DisplayBookMenu();
void  AddNewBookRecord();

void AddBookNode(struct myRefer **q);
void  AmendBookRecord();


void OpenAuthorFile();
void CloseAuthorFile();
void OpenPubFile();
void ClosePubFile();
void OpenBookFile();
void CloseBookFile();

bool SearchAuthor();
bool SearchPub();
bool SearchBook();
void DisplaySearchedBookRec();
bool WriteNewBookRecord();
void SearchByTitle();
/*======================declare function upon========================================================*/
int TotalAuthorNode=0;
int TotalPubNode=0;
int TotalBookNode=0;

char SearchedPubCode[7];
char SearchedAuthorCode[7];
char SearchedISBN[7];
char SearchedTitle[21];

int CurrPubRecNum=0;
int CurrBookNodeNum=0;
int CurrAuthorRecNum=0;

FILE *fBook;
FILE *fPub;
FILE *fAuthor;

struct Book
{
		char ISBN[7];
		char Title[21];
		float Price;
		int StockOnHand;
		int QuantitySold;
		char Status;
		char AuthorCode[21];
		char PublisherCode[21];
};
struct Book mybook;

struct Publisher
{
	 char PubCode[7];
	 char PubName[21];
	 char PubAddress[21];
};
struct Publisher pub;

struct Author{
	 char AuthorCode[7];
	 char AuthorName[21];
	 char AuthorAddress[21];
};
struct Author author;

/*------------------------------------------------*/
struct myRefer
{
		char Code[7];
		char Name[21];
		struct myRefer  *nextlink;
};
struct myRefer *mybookrefer;


struct AuthorRefer
{
		char Code[7];
		char Name[21];

};
struct AuthorRefer myauthorrefer[100];

struct PubRefer
{
		char Code[7];
		char Name[21];

};
struct PubRefer mypubrefer[100];
/*====================declare structure upon===========================================================*/


void main()
{

	// mypubrefer=(struct myRefer*)malloc(sizeof(struct myRefer));
	 mybookrefer=(struct myRefer*)malloc(sizeof(struct myRefer));

	 LoadAuthorRecord( );
	 LoadPubRecord( );
	 LoadToBookRefer(&mybookrefer);
	 bool isExit=false;

	 while(!isExit)
	 {
		DisplayBookMenu();
		char ch;
		gets(&ch);
		switch (ch){
			  case '1':
				  SearchByISBN();
				  break;
			  case '2':
				  SearchByTitle();
					break;
			  case '3':
					AddNewBookRecord();
					break;
			  case '4':
					AmendBookRecord();
					break;
			  case '5':
					isExit=true;
		     }
	 }
}
/*======================Book sub main upon=====================================================*/
void DisplayBookMenu()
{
    puts("if you want to search a book record by Book ISBN, press 1 please.");
	 puts("if you want to search a book record by Book Title, press 2 please.");
	 puts("if you want to add a book record, please enter 3./n");
	 puts("if you want to amend a exist book record, please enter 4.");
	 puts("if you want to shut down program, please enter 5.");
}
/*=====================================================================*/
void OpenAuthorFile()
{
	  fAuthor=fopen("a:\\author.txt", "r+");
	  if (fAuthor==0)
		  {puts("author file is not existed, create one?");
                   fAuthor=fopen("a:\\author.txt","w");
			fclose(fAuthor);
		  fAuthor=fopen("a:\\author.txt", "r+");
		  }
}
/*===================================open author file upon================================================*/
void CloseAuthorFile()
{
			fclose(fAuthor);
}
/*=================================close author file upon=============================================*/
void OpenPubFile()
{
	  fPub=fopen("a:\\publisher.txt", "r+" );
	  if (fPub==0)
		  {puts("publisher file is not existed, create one?");
                   fPub=fopen("a:\\publisher.txt","w");
			fclose(fPub);
		  fPub=fopen("a:\\publisher.txt", "r+");
		  }

}
/*=================open pub file==================================*/
void ClosePubFile()
{
	  fclose(fPub);
	  
}

/*=====================close pub file===================================*/

void OpenBookFile()
{
fBook=fopen("a:\\book.txt", "r" );
if (fBook==0)
	{puts("book file is not existed, create one?");
			fBook=fopen("a:\\book.txt", "w" );
	 CloseBookFile();
	 fBook=fopen("a:\\book.txt", "r+" );
	 }
}
/*=================open Book file==================================*/
void CloseBookFile()
{
	  fclose(fBook);
}

/*=====================close Book file===================================*/

void  LoadToBookRefer(struct myRefer **q)
{
	long offset;
	struct myRefer *temp;
	temp=*q;
	TotalBookNode=0;
	OpenBookFile();

	while (true){
		 if (fread(&mybook, sizeof(mybook),1,fBook)==1){
		  temp=(struct myRefer*)malloc(sizeof(struct myRefer));
		  AssignBookRefer(&temp);
		  temp=temp->nextlink;
		 
		 }
		 else 	break;
	 }
	CloseBookFile();
 
}
/*============================Load Book Record====================================================*/
void AssignBookRefer(struct myRefer **p)
{
	  struct myRefer *temp;
	  temp=*p;
	  long offset=sizeof(mybook)* TotalBookNode;
	  fseek(fBook, offset, 0);
	  fread(&mybook, sizeof(mybook), 1, fBook);
	  strcpy(temp->Code, mybook.ISBN);
	  strcpy(temp->Name, mybook.Title );
	   TotalBookNode++;
	  return;
}
/*=======================Assign book Refer================================*/
void AssignPubRefer(int index)
{

	  long offset=sizeof(pub)*TotalPubNode;
	  fseek(fPub, offset, 0);
	  fread(&pub, sizeof(pub), 1,fPub);
	  strcpy(mypubrefer[index].Code,pub.PubCode);
	  strcpy(mypubrefer[index].Name, pub.PubName);
	  TotalPubNode+=1;
}
/*=======================Assign Pub Refer================================*/
void AssignAuthorRefer(int index)
{


	  long offset=sizeof(author)*TotalAuthorNode;
	  fseek(fAuthor, offset, 0);
	  fread(&author, sizeof(author), 1,fAuthor);
	  strcpy(myauthorrefer[index].Code,author.AuthorCode);
	  strcpy(myauthorrefer[index].Name, author.AuthorName);
	  TotalAuthorNode+=1;
}
/*=======================Assign Author Refer================================*/

void SearchByISBN()
{
	 
	 puts("please enter searched book ISBN.");
	 gets(SearchedISBN);
	 while(true)
	 {
	 OpenBookFile();
	 if (SearchBook())
		  {
		  DisplaySearchedBookRec();
		  CloseBookFile();
		  return;
		  }
	 else
		 {
			 printf("not found.");
			 CloseBookFile();
			 puts("please enter book code for the record you want to search.");
			 gets(SearchedISBN);
		 }
	 }
}
/*===================================Search By ISBN==============================================*/
bool SearchBook()
{
	 int index=0;
	 struct myRefer *temp;
	 temp=mybookrefer;

	 if (TotalBookNode==0)
		 {puts("not found.");
		  return false;
		 }

	  while (index<=TotalBookNode)
	  {

		  if  (strcmp(SearchedISBN,mybookrefer->Code)==0)
				 {
				  CurrBookNodeNum=index;
				  return true;
				 }
		  else
				 {
				 index+=1;
				 temp=temp->nextlink;
				 }
	  }
	  return false;
}
/*===============================Search================================================*/
void DisplaySearchedBookRec()
{
		long offset;
		puts("following is the searched record details.");
		offset=sizeof(Book)*CurrBookNodeNum;
		fseek(fBook, offset, 0);
		fread(&mybook, sizeof(mybook), 1, fBook);
		puts(mybook.ISBN);
		puts(mybook.Title);
		printf("%.2f", mybook.Price);
		printf("%d", mybook.StockOnHand);
		printf("%d", mybook.QuantitySold);
		puts(&mybook.Status);
		puts(mybook.AuthorCode);
		puts(mybook.PublisherCode);
}
/*=============================Display Searched Book Rec======================================================*/
void  SearchByTitle()
{
	  int index=0;
     struct myRefer *temp;
	  temp=mybookrefer;
	  CurrBookNodeNum=0;
	  OpenBookFile();
	  puts("please enter Publisher name for the record you want to search.");
	  gets(SearchedTitle);
      if (TotalBookNode==0)
		  puts("not found.");
	  while(index<TotalBookNode)
		{
		  if (strcmp(SearchedTitle,mybookrefer->Name)==0 )
				{
				CurrBookNodeNum= index;
				DisplaySearchedBookRec();
				index+=1;
				temp=temp->nextlink;
				}
		  else
				{
				 index+=1;
				 temp=temp->nextlink;
				 }
	  }
	  CloseBookFile();
	  puts("not found,retry.");
}
/*==============================Search By Title=================================================*/

void AddNewBookRecord()
{
 

	 puts("enter new ISBN");
	 gets(SearchedISBN);
	 OpenBookFile();

		 if (SearchBook())
			 {
			  printf("this book record is existing in file./n");
			 }
		 else
			 {
			 if (!WriteNewBookRecord())
				 {
				  puts("Write error");

				 }
			 }
	 CloseBookFile();

}
/*=====================function add new book record upon=========================================================*/
bool WriteNewBookRecord()
{
  long offset;
	  char temp[21];
	  char temp_title[21];
	  char newprice[21];
	  float price;
	  int newStockOnHand;
	  int newQuantitySold;
	  char Status;
	  char existAuthorCode[21];
	  char existPublisherCode[21];


    offset=sizeof(pub)* TotalBookNode;
	  fseek(fPub, offset, 0);


	  if(strlen(SearchedISBN)>0 & strlen(SearchedISBN)<7)
		  {
			if (SearchBook())
				{
				puts("inputed ISBN has exist, process fail.");
				return false;
				}
		  }
	  else
		  {
			puts("entered ISBN is not valid, process fail.");
			return false;
		  }

		puts("please enter new book title.");
		gets(temp_title);
		if (strlen(temp_title)>0 & strlen(temp_title)<21)
			{
				strcpy(mybook.Title, temp_title);

			}
		else
			{
			 puts("entered title is not valid.");
			 return false;
			}

		puts("enter the price of this new book.");
		gets(newprice);

		if(strlen(newprice)>=0 )
			{
			price=atof(newprice);
			if (price>=0 )
				 mybook.Price=atof(newprice);
			else
				  {puts("entered price is not valid, process fail.");
				  return false;
				  }
			}
		else
			{
			 puts("entered price is not valid, process fail.");
			 return false;
			}

		puts("enter stock on hand.");
		scanf("%d", newStockOnHand);
		if (newStockOnHand>=0)
			 {
			 mybook.StockOnHand=newStockOnHand;
			 }
		else
			{
			 puts("entered stock on hand is not valid, process fail.");
			 return false;
			}

		puts("enter Quantity sold.");
		scanf("%d", &newQuantitySold);
		if (newQuantitySold>=0)
			 mybook.QuantitySold=newQuantitySold;
		else
			{gets("entered quantity is not valid, process fail.");
			 return false;
			}

		puts("enter status.");
		puts("enter 0 stand for current status, 1 stand for out of print, 2 stand for delete.enter please");

		scanf("%s",&Status);

		if (Status=='0' || Status=='1' || Status=='2')
			 {
			 mybook.Status=Status;
			 }
		else                            
			 {
			  puts("entered status is not valid.");
			  return false;
			 }

		puts("enter exist author code.");
     	scanf("%s",SearchedPubCode);
	  //	gets(SearchedAuthorCode);
		if (SearchAuthor())
			{
			strcpy(mybook.AuthorCode,SearchedAuthorCode);
			}
		else
		  { puts("enter author code is not exist, you have to enter a exist one, process fail.");
			 return false;
		  }


		puts("enter exist publisher code.");
		scanf("%s",SearchedPubCode);
		if (SearchPub())
			{
				strcpy(mybook.PublisherCode,  SearchedPubCode);
			}
		else
			{
				puts("enter  publisher code no exist, you have to choose a exist one, process fail.");
				return false;
			}


		AddBookNode(&mybookrefer);
		fwrite(&mybook, sizeof(mybook), 1, fBook );
		fflush(stdin);
		TotalBookNode+=1;
		puts("new record is successfully added.");
		return true;
}
/*============================function write new book record upon==================================================*/
void AddBookNode(struct myRefer **q)
{

	  int index=0;
	  struct  myRefer *temp;


		  if (TotalBookNode==0 || *q==NULL)
		  {
			  *q=(struct myRefer*)malloc(sizeof(struct myRefer));
			  temp=*q;
			  AssignBookRefer(&temp);
		  }
		  else
		  {
				while(index<=TotalBookNode)
				{
				temp=temp->nextlink;
				index+=1;
				}
				temp->nextlink=(struct myRefer*)malloc(sizeof(struct myRefer) );
				AssignBookRefer(&temp);

		  }

}
/*=============================Add New Book Node=============================================*/

void  AmendBookRecord()
{
	  int a;
	  long offset;
	  float temp_price;
	  int temp_status;

	  int temp_ItemsSold;
	  int temp_quantity;
	  int temp_StockOnHand;
	  char temp_Title[21];

	  start2:
	  fflush(stdin);
	  puts("the book record is updated only by reducing the stock on hand and increasing the quantity sold; change price or change status.");
	  puts("enter ISBN for record you want to amend");
	  gets(SearchedISBN);


	  if ( SearchBook()==false)
			{printf("searched book is not exist.");
			return;
			}

	  offset=sizeof(mybook)* CurrBookNodeNum;
	  fseek(fBook, offset, 0);
	  fread(&mybook, sizeof(mybook), 1, fBook);
/*amend book price*/
			
	puts("enter new updated value for book price./n");
	scanf("temp_price=%.2f",temp_price);
	if(temp_price<0)
	   {puts("entered price is not valid.");
	    return;
	   }
	else
	    mybook.Price=temp_price;
	    

/*amend status*/
                   puts(&mybook.Status);
		  puts("please amend status,input 0 for current or 1 for out of print or 2 for deleted .");
		 
		 scanf("%d", temp_status);
		  switch   (temp_status)
		  {
			  case '0':
					 mybook.Status= temp_status;
					 break;
			  case '1':
					 mybook.Status= temp_status;
					 break;
			  case '2':
			       mybook.Status= temp_status;
					 break;
			default:
					  printf("status must be 0 or 1 or 2");
					 break;
					  
		  }
/*amend stock on hand*/
	 puts("please amend stock on hand.");
	 scanf("amend stock on hand=%d", temp_StockOnHand);
	 if (temp_StockOnHand<0)
		 {puts("stock on hand can not less than 0.");
		  return;
		 }
	 else
	     mybook.StockOnHand=temp_StockOnHand;

/* amend stock on quantity sold and stock on hand */
	 puts("enter items sold.");
	 scanf("temp_ItemsSold=%d", temp_ItemsSold );
	 if(temp_ItemsSold<=0)
		{puts("entered sold_items is not valid.");
		 return;
		}
	if( temp_ItemsSold< mybook.StockOnHand)
		{puts("not enough stock on hand, inputed items sold is not valid.");
		 return;
		}
	else
	  {
		 mybook.QuantitySold =mybook.QuantitySold +  temp_ItemsSold;
		 mybook.StockOnHand=mybook.StockOnHand- temp_ItemsSold;
	  }




	 offset=sizeof(mybook)*CurrBookNodeNum;
	 fseek(fAuthor, offset, 0);
	 fwrite(&author, sizeof(author),1,fAuthor);
	 fflush(stdin);

	 puts("amend record successful.");
	 CloseBookFile();

}
/*========================function Ament Author Record upon=====================================================*/


bool SearchAuthor()
{
		 int index=0;

	  if  (TotalAuthorNode==0 )
		  { puts("file is empty.");
			 return false;
		  }
	  while (index<=TotalAuthorNode)
	  {

		  if  (strcmp(SearchedAuthorCode,myauthorrefer[index].Code)==0)
		  {	CurrAuthorRecNum=index;
				return true;
		  }
		  else
				{index+=1;

				}
	  }

	  return false;
}
/*========================function search upon===================================================== */

bool SearchPub()
{
  int index=0;


  if (TotalPubNode==0)
		{puts("not found");
		return false;
		}
  while (index<TotalPubNode)
	  {

		  if  (strcmp(SearchedPubCode,mypubrefer[index].Code)==0)
		  {     CurrPubRecNum=index;
			return true;
		  }
		  else
				{index+=1;
				}
	  }

	  return false;
}
/*========================function search upon======================================================*/


void  LoadPubRecord( )
{

	long offset;
	 int index=0;

	TotalPubNode=0;
	OpenPubFile();

	while (true){
		 if (fread(&pub, sizeof(pub),1,fPub)==1)
		 {

		  AssignPubRefer(index);
		  index++;

		 }
		 else 	break;
	  }
	ClosePubFile();

				    
			  
		 return;
 }

/*======================load publisher code to array===================================================*/
void  LoadAuthorRecord()
{
	long offset;
	struct myRefer *temp;
	int index=0;

	TotalAuthorNode=0;
	OpenAuthorFile();

	while (true){
		 if (fread(&author, sizeof(author),1,fAuthor)==1){

		  AssignAuthorRefer(index);

		 
		 }
		 else 	break;
	 }
	CloseAuthorFile();


}

/*========================Load Author Record upon=======================================================*/

















































































